package com.lan.service.sys.impl;

import com.lan.SysConstants;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lan.entity.sys.Menu;
import com.lan.entity.sys.RoleMenu;
import com.lan.mapper.sys.MenuMapper;
import com.lan.mapper.sys.RoleMenuMapper;
import com.lan.service.sys.MenuService;
import com.lan.utils.tree.TreeBuilder;
import com.lan.utils.tree.TreeNode;
import com.lan.utils.tree.TreeTableNode;
import com.lan.viewObject.Query;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * <p>
 *  菜单 ServiceImpl
 * </p>
 *
 * @author shadow
 * @since 2022-06-04
 */
@Service
public class MenuServiceImpl implements MenuService {

    protected final Logger LOGGER = LoggerFactory.getLogger(getClass());

    @Resource
    private MenuMapper menuMapper;
    @Resource
    private RoleMenuMapper roleMenuRelMapper;

    /**
     * 查询 -> id
     *
     * @param id id
     * @return Menu
     * */
    @Override
    public Menu getById(final String id) {
        return menuMapper.selectById(id);
    }

    /**
     * 查询 -> 角色id
     *
     * @param roleId roleId
     * @return list
     * */
    @Override
    public List<Menu> getMenuListByRoleId(final String roleId) {
        // 角色id -> 菜单id list
        RoleMenu roleMenuRel = new RoleMenu();
        roleMenuRel.setRoleId(roleId);
        List<RoleMenu> roleMenuRelList = getList(roleMenuRel, new QueryWrapper<>());
        List<String> menuIdList = new ArrayList<>();
        roleMenuRelList.forEach(x -> menuIdList.add(x.getMenuId()));
        // 获取菜单列表
        List<Menu> menuList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(roleMenuRelList)) {
            QueryWrapper<Menu> query = new QueryWrapper<>();
            query.in("id", menuIdList);
            query.orderByAsc("order_num");
            menuList = menuMapper.selectList(query);
        }
        return menuList;
    }

    /**
     * 查询 -> 菜单树
     *
     * @return list
     */
    @Override
    public List<TreeNode<Menu>> getMenuTree(final String roleId) {
        List<Menu> menuList = getList(new Menu(), new QueryWrapper<>());
        List<Menu> menuListByRoleId = this.getMenuListByRoleId(roleId);
        return TreeBuilder.createTree(menuList, menuListByRoleId, SysConstants.PARENT_ID);
    }

    /**
     * 查询 -> 条件查询 QueryWrapper
     *
     * @param menu menu
     * @return list
     */
    @Override
    public List<Menu> getListByWrapper(Menu menu) {
        return getList(menu, new QueryWrapper<>());
    }

    /**
     * 查询 -> 分页查询 QueryWrapper
     *
     * @param query query
     * @return iPage
     */
    @Override
    public IPage<Menu> getPageByWrapper(final Query<Menu> query) {
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        Optional.ofNullable(query.getName())
                .filter(StringUtils::isNotBlank)
                .ifPresent(x -> wrapper.eq("name", x)
        );
        wrapper.orderByAsc("order_num");
        return menuMapper.selectPage(new Page<>(query.getPage(),query.getLimit()), wrapper);
    }

    /**
     * 查询 -> 树形表格
     *
     * @param query query
     * @return list
     */
    @Override
    public List<TreeTableNode> getTreeTableList(Query<Menu> query) {
        List<TreeTableNode> treeTableNodeList = new ArrayList<>();
        List<Menu> list = menuMapper.selectList(new QueryWrapper<>());
        list.forEach(x -> {
            TreeTableNode treeTableNode = x.toTreeTable();
            treeTableNodeList.add(treeTableNode);
        });
        return treeTableNodeList;
    }

    /**
     * 新增
     *
     * @param menu menu
     * @return int
     */
    @Override
    public int save(Menu menu) {
        menu.setId(UUID.randomUUID().toString());
        return menuMapper.insert(menu);
    }

    /**
     * 更新 -> id
     *
     * @param menu menu
     * @return int
     */
    @Override
    public int updateById(final Menu menu) {
        Menu entity = menuMapper.selectById(menu.getId());
        if (null == entity) {
            System.out.println("updateById(:menu) <<<<< failed >>>>> 菜单不存在");
            return 0;
        }
        return menuMapper.updateById(menu);
    }

    /**
     * 删除 -> id
     *
     * @param id id
     * @return int
     */
    @Override
    public int deleteById(final String id) {
        Menu menu = menuMapper.selectById(id);
        if (null == menu) {
            LOGGER.info("deleteById(:id) <<<<< failed >>>>> 菜单不存在 id : {}", id);
            return 0;
        }
        return menuMapper.deleteById(id);
    }


    private List<Menu> getList(Menu menu, QueryWrapper<Menu> query) {
        if (null != menu) {
            Optional.ofNullable(menu.getId())
                    .filter(StringUtils::isNotBlank)
                    .ifPresent(x -> query.eq("id", x));
            Optional.ofNullable(menu.getName())
                    .filter(StringUtils::isNotBlank)
                    .ifPresent(x -> query.eq("name", x));
            Optional.ofNullable(menu.getParentId())
                    .filter(StringUtils::isNotBlank)
                    .ifPresent(x -> query.eq("parent_id", x));
        }
        return menuMapper.selectList(query);
    }

    private List<RoleMenu> getList(RoleMenu roleMenuRel, QueryWrapper<RoleMenu> query) {
        Optional.ofNullable(roleMenuRel.getId())
                .filter(StringUtils::isNotBlank)
                .ifPresent(x -> query.eq("id", x));
        Optional.ofNullable(roleMenuRel.getRoleId())
                .filter(StringUtils::isNotBlank)
                .ifPresent(x -> query.eq("role_id", x));
        Optional.ofNullable(roleMenuRel.getMenuId())
                .filter(StringUtils::isNotBlank)
                .ifPresent(x -> query.eq("menu_id", x));
        return roleMenuRelMapper.selectList(query);
    }
}
